import * as fs from 'fs-extra';
import * as path from 'path';

import { extractZipTo, createTempDirectory } from '$common';

export class TreeNode {
  public title: string;
  public value: string;
  public absPath: string;
  public isLeaf: boolean;
  public children: TreeNode[];

  constructor(name: string, absPath: string, relativePath: string) {
    this.title = name;
    this.value = relativePath;
    this.absPath = absPath;
    this.isLeaf = false;
    this.children = [];
  }
}

export class DirectoryTreeReader {

  async fromZip(zipFilePath: string) {
    const tempDir = createTempDirectory();
    await extractZipTo(zipFilePath, tempDir);
    const trees = await this.fromDirectory(tempDir);
    await fs.remove(tempDir);
    return trees;
  }

  async fromDirectory(rootPath: string): Promise<TreeNode> {
    const root = new TreeNode(path.basename(rootPath), rootPath, '.');
    const stack = [root];
    while (stack.length) {
      const currentNode = stack.pop();

      if (currentNode) {
        const children = await fs.readdir(currentNode.absPath);
        for (let child of children) {
          const childPath = path.join(currentNode.absPath, child);
          const childNode = new TreeNode(path.basename(childPath), childPath, path.relative(rootPath, childPath));
          currentNode.children.push(childNode);
  
          if (fs.statSync(childNode.absPath).isDirectory()) {
            stack.push(childNode);
          } else {
            childNode.isLeaf = true;
          }
        }
      }
    }
    return root;
  }
}

// (async () => {
//   console.log(JSON.stringify(await new DirectoryTreeReader().fromDirectory('/Users/ellison/sim-agent/script'), null, 4));
// })();

// (async () => {
//   console.log(JSON.stringify(await new DirectoryTreeReader().fromZip('/Users/ellison/sim-agent/script/test.zip'), null, 4));
// })();